# -*- coding:utf8 -*-
__author__ = 'Forcs'

from django.conf.urls import url
from django.core.urlresolvers import reverse

from wanbatvcom.http.whttp import send_error_response_with_message, send_ok_response_with_data
from wanbatvcom.http.decorators import require_params, check_login
from wancake.resmng.models import Member, Group, Rule
from wanbatvcom.utils import make_token
from wancake.auth import encode_password
from wancake.view.render import DashboardRender

import datetime
import time
import copy

def _check_and_refresh_cached_data(list_cached, model_class):
    length = len(list_cached)
    if length == 0:
        return _refresh_cached_data(list_cached, model_class, include_id=True)
    else:
        return list_cached

def _refresh_cached_data(list_cached, model_class, include_id=False):
        if list_cached is None:
            list_cached = []
        else:
            del list_cached[:]

        qs = model_class.objects.all()
        if qs.exists():
            for model in qs:
                list_cached.append(model.to_json(raw_id_column_name='', include_id=include_id))

        return list_cached

def _render(view_name, request, context=None):
    session_id = request.GET["session"]
    render = DashboardRender(view_name, session_id=session_id)
    return render.render(request, context=context)

class ResourceManagement(object):

    def __init__(self, name='resmng'):
        self.name = name
        self._rules = list()
        self._groups = list()
        self._members = list()

    @property
    def urls(self):
        urlpatterns = [
            url(r'^index$', self.index, name='res_index'),
            url(r'^member/add$', self.member_add, name='res_member_add'),
            url(r'^member/add/done$', self.member_add_done, name='res_member_add_done'),
            url(r'^member/check/(?P<account>\S+)$', self.check_member_account),
            url(r'^member/all$', self.get_members, name='res_member_all'),
            url(r'^member/edit/(?P<token>\S+)$', self.member_edit, name='res_member_edit'),
            url(r'^member/edit/(?P<token>\S+)/done$', self.member_edit_done, name='res_member_edit_done'),
            url(r'^member/remove$', self.member_remove, name='res_member_remove'),
            url(r'^group/add$', self.group_add, name='res_group_add'),
            url(r'^group/add/done$', self.group_add_done, name='res_group_add_done'),
            url(r'^groups/all', self.get_groups, name="res_get_all_groups"),
            url(r'^rule/add$', self.rule_add, name='res_rule_add'),
            url(r'^rule/add/done$', self.rule_add_done, name='res_rule_add_done'),
            url(r'^rules/all$', self.get_rules, name="res_get_all_rules"),
            url(r'^rules/(?P<group_id>\d+)$', self.get_rules),
            url(r'^rules/groupid/(?P<group_id>\d+)$', self.get_rules),
            url(r'^rules/groupname/(?P<group_name>\D+)$', self.get_rules),
        ]
        return urlpatterns

    @require_params(params=["rule-name", "group-id"], method="POST")
    def rule_add_done(self, request):
        """
        添加角色
        :param request:
        :return:
        """
        name = request.POST["rule-name"]
        group_id = int(request.POST["group-id"])
        try:

            try:
                group = Group.objects.get(id=group_id)
            except Group.DoesNotExist:
                return send_error_response_with_message(u'查无分组id %d' % group_id)

            model = Rule(name=name)
            model.group = group
            model.save()

            self._rules = _refresh_cached_data(self._rules, Rule, include_id=True)

            return send_ok_response_with_data(data={
                "newId": model.id
            }, message=u'添加角色 %s 成功' % name)

        except Exception as e:
            return send_error_response_with_message(message=u'添加角色 %s 失败' % name)

    def _get_rules(self, group_id=None):
        """
        根据group_id获取角色列表，如果group_id为None，则获取全部角色列表
        :param group_id: 指定的分组id
        :return:
        """
        length = len(self._rules)
        if length == 0:
            self._rules = _refresh_cached_data(self._rules, Rule, include_id=True)

        result_list = list()

        length = len(self._rules)
        if length > 0:
            for rule_item in self._rules:
                group = rule_item["group"]
                if group["id"] == group_id or group_id is None:
                    item = rule_item.copy()
                    del item["group"]
                    item["groupId"] = group_id if group_id is not None else group.id
                    result_list.append(item)

        return result_list

    def get_rules(self, request, group_id=None):
        return send_ok_response_with_data({
            "list": self._get_rules(int(group_id))
        })

    @check_login()
    def rule_add(self, request):
        return _render("res_mng_rule_add.html", request, context={
            "group_list": self._get_groups()
        })

    @require_params(params=["group-name"], method='POST')
    def group_add_done(self, request):
        """
        添加
        :param request:
        :return:
        """
        name = request.POST["group-name"]
        try:
            model = Group(name=name)
            model.save()

            self._groups = _refresh_cached_data(self._groups, Group, include_id=True)

            return send_ok_response_with_data(data={
                "newId": model.id
            }, message=u'添加分组 %s 成功' % name)
        except Exception as e:
            return send_error_response_with_message(message=u'添加分组 %s 失败，%s' % (name, e.message))

    def _get_groups(self):
        """
        获取所有分组
        :return:
        """
        length = len(self._groups)
        if length == 0:
            self._groups = _refresh_cached_data(self._groups, Group, include_id=True)

        return self._groups

    def get_groups(self, request):
        return send_ok_response_with_data({
            "list": self._get_groups()
        })

    @check_login()
    def group_add(self, request):
        return _render("res_mng_group_add.html", request)

    @require_params(["account", "email", "password", "groupid", "ruleid"], method="POST")
    def member_add_done(self, request):
        body = request.POST

        member = {}
        account = body["account"]

        if not self.check_member_account(account):
            return send_error_response_with_message(message=u'用户 %s 已存在' % account)

        password = body["password"]
        group_id = int(body["groupid"])
        rule_id = int(body["ruleid"])

        member["account"] = account
        member["password"] = encode_password(password)
        member["email"] = body["email"]
        member["group_id"] = group_id
        member["rule_id"] = rule_id

        now = datetime.datetime.now()
        member["date_added"] = now
        member["date_last"] = now
        member["is_invalid"] = False
        member["is_active"] = False
        member["session_id"] = None

        timestamp = time.mktime(now.timetuple())
        member["token"] = make_token("{}{}{}{}{}", account, password, group_id, rule_id, timestamp)

        keys = body.keys()
        if "firstname" in keys:
            member["first_name"] = body["firstname"]
        if "lastname" in keys:
            member["last_name"] = body["lastname"]

        try:
            model = Member(**member)
            model.save()

            self._members = _refresh_cached_data(self._members, Member, include_id=True)

            return send_ok_response_with_data({
                "account": model.account,
                "group": model.group_id,
                "rule": model.rule_id,
                "token": model.token
            })

        except Exception as e:
            return send_error_response_with_message(message=e.message)

    def find_member(self, account=None, token=None):
        members = self._get_members()
        for member in members:
            if account and member["account"] == account:
                return member
            if token and member["token"] == token:
                return member
        return None

    def check_member_account(self, account=None):
        """
        检查账号account是否已经注册了，没有注册就返回true，否则返回false
        :param request:
        :param account: 将被检查的账号
        :return:
        """
        found = False
        members = self._get_members()
        for member in members:
            if member["account"] == account:
                found = True
                break

        return not found

    def _get_members(self, group_id=None, rule_id=None):
        self._members = _check_and_refresh_cached_data(self._members, Member)
        result_members = []
        for member in self._members:

            if member["is_invalid"]:
                continue

            if not group_id and not rule_id:
                result_members.append(member)
            else:
                except_item = None
                if group_id and member.group_id == group_id:
                    except_item = member

                if rule_id:
                    if member.rule_id != rule_id and except_item is not None:
                        except_item = None
                    elif member.rule_id == rule_id and except_item is None:
                        except_item = member

                if except_item is not None:
                    result_members.append(except_item)

        return result_members

    @require_params(["page"])
    def get_members(self, request):

        query = request.GET
        keys = query.keys()
        page_number = int(query["page"])
        page_size = 15
        if "pagesize" in keys:
            page_size = int(query["pagesize"])

        members = self._get_members()
        total = len(members)
        total_page_size = int(total / page_size)
        if total % page_size:
            total_page_size += 1

        # 拷贝一份临时的列表
        start = (page_number - 1) * page_size
        end = min(start + page_size, total)
        start = min(start, end)

        temp = []
        if members:
            for member in members[start: end]:
                temp.append(copy.copy(member))

        for member in temp:
            group = member["group"]
            rule = member["rule"]

            member["group"] = group["name"]
            member["isSuper"] = group["id"] == 30 and rule["id"] == 5
            member["isCp"] = group["id"] == 31
            member["rule"] = rule["name"]

        return send_ok_response_with_data(data={
            "list": temp,
            "totalPageSize": total_page_size,
            "currentPage": page_number
        })

    @check_login()
    def member_add(self, request):
        import copy
        group_list = copy.copy(self._get_groups())
        admin_group = group_list[0]
        admin_rules = self._get_rules(admin_group["id"])
        admin_group["super_admin_id"] = admin_rules[0]["id"]
        admin_group["normal_admin_id"] = admin_rules[1]["id"]
        admin_group["default_rule"] = admin_group["normal_admin_id"]

        cp_group = group_list[1]

        cp_rules = self._get_rules(cp_group["id"])
        cp_group["rules"] = cp_rules
        cp_group["default_rule"] = cp_rules[0]["id"]

        context = {
            "admin_group": admin_group,
            "cp_group": cp_group,
        }

        return _render("res_mng_member_add.html", request, context=context)

    @check_login()
    def member_edit(self, request, token):
        """
        返回成员编辑页面
        :param request:
        :param token: 成员的token
        :return:
        """
        return _render("res_mng_member_edit.html", request, context={"token": token})

    def member_edit_done(self, request):
        """
        编辑完成后，将新数据更新到数据库
        :param request:
        :param token: 成员的token
        :return:
        """
        pass

    @require_params(["token"], method="POST")
    def member_remove(self, request):
        body = request.POST
        token_removed = body["token"]

        members = self._get_members()
        removed = False
        message = None
        for member in members:
            if member["token"] == token_removed:
                member["is_invalid"] = False
                try:
                    Member.objects.filter(token=token_removed).update(is_invalid=True)
                    removed = True
                except Exception as e:
                    message = e.message

                break

        if removed:
            self._members = _refresh_cached_data(self._members, Member, include_id=True)
            return send_ok_response_with_data(data={
                "token": token_removed
            })
        else:
            if not message:
                message = u'查无此人'
            return send_error_response_with_message(message=message)

    def update_member(self, update):
        if "account" in update.keys():
            account = update["account"]
            del update["account"]
            Member.objects.filter(account=account).update(**update)
        else:
            Member.objects.update(**update)
        # 更新完之后刷新缓存列表
        _refresh_cached_data(self._members, Member, include_id=True)

    @check_login()
    def index(self, request):
        session_id = request.GET["session"]
        return _render("res_mng_index.html", request, context={
            "href_member_add": "{}?session={}".format(reverse(self.member_add), session_id)
        })

resmng = ResourceManagement()
